package com.pabble.webnative;

import android.app.Activity;

import android.util.Log;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;

/**
 * 下载工具类
 * martin
 * 2021.7.21
 */
public class DownloadUtil {
    private static final String TAG = DownloadUtil.class.getName();
    private final OkHttpClient okHttpClient;
    private FileUtil fileUtil;

    public DownloadUtil(Activity ctx) {
        okHttpClient = new OkHttpClient();
        fileUtil = new FileUtil();
    }



    public void download(final String url, final String saveDir,
                         final OnDownloadListener listener) {
        Request request = new Request.Builder().url(url).build();
        okHttpClient.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                // 下载失败
                listener.onDownloadFailed();
            }


            @Override
            public void onResponse(Call call, Response response) throws IOException {
                InputStream is = null;
                byte[] buf = new byte[2048];
                int len = 0;
                FileOutputStream fos = null;
                // 储存下载文件的目录
                String savePath = isExistDir(saveDir);
                try {
                    is = response.body().byteStream();
                    long total = response.body().contentLength();
                    File file = new File(savePath, getNameFromUrl(url));
                    fos = new FileOutputStream(file);
                    long sum = 0;
                    while ((len = is.read(buf)) != -1) {
                        fos.write(buf, 0, len);
                        sum += len;
                        int progress = (int) (sum * 1.0f / total * 100);
                        // 下载中
                        listener.onDownloading(progress);
                    }
                    fos.flush();
                    // 下载完成
                    listener.onDownloadSuccess(file);
                } catch (Exception e) {
                    listener.onDownloadFailed();
                } finally {
                    try {
                        if (is != null)
                            is.close();
                    } catch (IOException e) {
                    }
                    try {
                        if (fos != null)
                            fos.close();
                    } catch (IOException e) {
                    }
                }
            }
        });
    }

    /**
     * saveDir
     * 判断下载目录是否存在
     */
    private static String isExistDir(String saveDir) throws IOException {
        // 下载位置
        File downloadFile = new File(saveDir);
        if (!downloadFile.mkdirs()) {
            Log.i(TAG,"创建文件夹:"+saveDir);
            downloadFile.createNewFile();
        }
        String savePath = downloadFile.getAbsolutePath();
        return savePath;
    }

    public static String getNameFromUrl(String url) {
        return url.substring(url.lastIndexOf("/") + 1);
    }

    public class ZipFile {
        public String name;
        public int size;

        ArrayList<byte[]> buffers;
        public ZipFile(String n){
            name = n;
            buffers = new ArrayList<byte[]>();
        }
    }

    private int getZipSize(String zipPtath) throws IOException{
        // 打开压缩文件
        File file;
        InputStream inputStream = new FileInputStream(zipPtath); ;
        ZipInputStream zipInputStream = new ZipInputStream(inputStream);

        // 读取一个进入点
        ZipEntry zipEntry = zipInputStream.getNextEntry();
        // 使用1Mbuffer
        byte[] buffer = new byte[1024 * 1024];
        // 解压时字节计数
        int count = 0;
        int allSize = 0;
        // 如果进入点为空说明已经遍历完所有压缩包中文件和目录
        while (zipEntry != null) {
            if (!zipEntry.isDirectory()) {  //如果是一个文件
                while ((count = zipInputStream.read(buffer)) > 0) {
                    allSize += count;
                }
            }
            zipEntry = zipInputStream.getNextEntry();
        }
        zipInputStream.close();
        return allSize;
    }

    public void unzipFile(String zipPtath, String outputDirectory, OnUnZipListener listener)throws IOException {
        /**
         * 解压assets的zip压缩文件到指定目录
         * @param context上下文对象
         * @param assetName压缩文件名
         * @param outputDirectory输出目录
         * @param isReWrite是否覆盖
         * @throws IOException
         */

        Log.i(TAG,"开始解压的文件： "  + zipPtath + "\n" + "解压的目标路径：" + outputDirectory);

        fileUtil.DeleteFolder(outputDirectory);
        String tempFold = outputDirectory+"_temp";
        fileUtil.DeleteFolder(tempFold);
        // 创建解压目标目录
        File tempFile = new File(tempFold);
        // 如果目标目录不存在，则创建
        if (!tempFile.exists()) {
            boolean mk = tempFile.mkdirs();
            if(mk == false){
                throw new Error("没有外部文件权限:"+tempFold);
            }
        }
        int allSize = 0;
        if(listener != null){
            allSize = getZipSize(zipPtath);
            listener.OnStart(allSize);
        }

        // 打开压缩文件
        InputStream inputStream = new FileInputStream(zipPtath); ;
        ZipInputStream zipInputStream = new ZipInputStream(inputStream);

        // 读取一个进入点
        ZipEntry zipEntry = zipInputStream.getNextEntry();
        // 使用1Mbuffer
        byte[] buffer = new byte[1024 * 1024];
        // 解压时字节计数
        int count = 0;
        int currentSize = 0;
        // 如果进入点为空说明已经遍历完所有压缩包中文件和目录
        int lastPro = -1;
        File file;
        while (zipEntry != null) {
            if (!zipEntry.isDirectory()) {  //如果是一个文件
                Log.i(TAG,"解压文件:"+tempFold + File.separator + zipEntry.getName());
                file = new File(tempFold + File.separator + zipEntry.getName());  //放到新的解压的文件路径

                file.createNewFile();
                FileOutputStream fileOutputStream = new FileOutputStream(file);
                while ((count = zipInputStream.read(buffer)) > 0) {
                    fileOutputStream.write(buffer, 0, count);
                    currentSize += count;
                    if(listener != null && allSize != 0){
                        int pro = currentSize * 100 /allSize;
                        if(pro != lastPro){
                            lastPro = pro;
                            listener.onProgress(currentSize, pro);
                        }
                    }
                }
                fileOutputStream.close();
            } else {
                new File(tempFold + File.separator + zipEntry.getName()).mkdirs();
            }

            // 定位到下一个文件入口
            zipEntry = zipInputStream.getNextEntry();
        }
        zipInputStream.close();

        File newFile = new File(outputDirectory);
        tempFile.renameTo(newFile);
        if(listener != null){
            listener.onSuccess();
        }
    }

    public interface OnDownloadListener {
        /**
         * 下载成功
         */
        void onDownloadSuccess(File file);

        /**
         * @param progress 下载进度
         */
        void onDownloading(int progress);

        /**
         * 下载失败
         */
        void onDownloadFailed();
    }

    public interface OnUnZipListener {
        /**
         * 开始解压 总文件大小
         */
        void OnStart(int size);

        /**
         * @param current 当前数量
         * @param progress 进度
         */
        void onProgress(int current,int progress);
        void onSuccess();
        void onFaild(Error err);
    }
}